package com.koron.tool.frame;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

import com.koron.beetl.BeetlTool;
import com.koron.localdb.ConnectionBean;
import com.koron.localdb.LocalMapper;
import com.koron.mybatis.SessionFactory;
import com.koron.mybatis.SqlTask;
import com.koron.tool.Constant;
import com.koron.ui.ChangeAction;
import com.koron.ui.MutableGridLayout;

/**
 * 数据库配置界面
 * 
 * @author swan
 *
 */
public class DBSettingFrame extends JInternalFrame {
	
	private final JTextField txtDriver = new JTextField("org.gjt.mm.mysql.Driver");
	private final JTextField txtAlias = new JTextField("_default");
	private final JTextField txtUrl = new JTextField("");
	private final JTextField txtPwd = new JTextField("123456");
	private final JTextField txtUser = new JTextField("sa");
	private final JTextField txtPort = new JTextField("3306");
	private final JTextField txtHost = new JTextField("localhost");
	private final JTextField txtDbName = new JTextField("db");
	private final DefaultTableModel dtm = new DefaultTableModel(new String[] { "别名", "数据库名", "账号", "密码", "主机", "端口", "url" },
			0);
	private final JComboBox<DBType> dbType = new JComboBox<DBType>(new DBType[] { DBType.MSSQL, DBType.MYSQL, DBType.SQLITE });

	private static DBSettingFrame instance;

	public static synchronized DBSettingFrame getInstance() {
		if (instance != null && !instance.isClosed)
			return instance;
		instance = new DBSettingFrame();
		return instance;
	}

	private DBSettingFrame() {
		super("数据库设置");
		setSize(600, 400);
		setMaximizable(true);
		setClosable(true);
		setIconifiable(true);
		setResizable(true);
		MutableGridLayout layout = new MutableGridLayout(4, 7, 5, 5);
		layout.merge(0, 0, 3, 0);
		layout.merge(0, 4, 3, 4);
		layout.merge(0, 6, 3, 6);
		layout.getBox(0, 6).split(3, 1);
		layout.setWidth(0, 80);
		layout.setWidth(2, 80);
		layout.setHeight(1, 30);
		layout.setHeight(2, 30);
		layout.setHeight(3, 30);
		layout.setHeight(4, 30);
		layout.setHeight(5, 30);
		layout.setHeight(6, 30);
		
		getContentPane().setLayout(layout);
		final JTable jtb = new JTable(dtm) {
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		};
		jtb.getColumnModel().getColumn(0).setCellRenderer(Constant.getTableRender());
		jtb.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		jtb.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				if(jtb.getSelectedRow()!=-1)
					loadBean(String.valueOf(jtb.getValueAt(jtb.getSelectedRow(), 0)));
			}
		});
		jtb.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
		jtb.setRowHeight(30);
		JScrollPane jsp = new JScrollPane(jtb);
		jsp.setPreferredSize(new Dimension(10, 10));
		getContentPane().add(jsp);
		getContentPane().add(new JLabel("连接名"));
		getContentPane().add(txtAlias);
		getContentPane().add(new JLabel("数据库类型"));
		getContentPane().add(dbType);
		getContentPane().add(new JLabel("驱动"));
		getContentPane().add(txtDriver);
		getContentPane().add(new JLabel("数据库名"));
		getContentPane().add(txtDbName);
		getContentPane().add(new JLabel("主机"));
		getContentPane().add(txtHost);
		getContentPane().add(new JLabel("端口"));
		getContentPane().add(txtPort);
		getContentPane().add(txtUrl);
		getContentPane().add(new JLabel("账号"));
		getContentPane().add(txtUser);
		getContentPane().add(new JLabel("密码"));
		getContentPane().add(txtPwd);
		getContentPane().add(new JButton(new SaveAction(this)));
		getContentPane().add(new JButton(new DeleteAction(this)));
		getContentPane().add(new JButton(new TestConnection(this)));
		new ChangeAction() {
			@Override
			public void action() {
				renderURL();
			}
		}.addComponent(txtAlias,txtDbName,txtDriver,txtHost,txtPort,txtPwd,txtUser,dbType);
		dbType.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				txtDriver.setText(dbType.getModel().getElementAt(dbType.getSelectedIndex()).driver);
			}
		});
		loadDBList();
		jtb.setRowSelectionInterval(0, 0);
		renderURL();
		setVisible(true);
	}
	/**
	 * 重新生成URL
	 */
	private void renderURL() {
		String url = dbType.getModel().getElementAt(dbType.getSelectedIndex()).urlPattern;
		final ConnectionBean bean = new ConnectionBean();
		bean.setAlias(txtAlias.getText());
		bean.setDbname(txtDbName.getText());
		bean.setDriver(txtDriver.getText());
		bean.setHost(txtHost.getText());
		bean.setPassword(txtPwd.getText());
		try {
			bean.setPort(Integer.parseInt(txtPort.getText()));
		} catch (NumberFormatException e) {
		}
		bean.setUrl(txtUrl.getText());
		bean.setUser(txtUser.getText());
		BeetlTool tool = BeetlTool.getIntance();
		tool.put("bean", bean);
		url = tool.render(url);
		txtUrl.setText(url);
	}
	
	void loadBean(String alias)
	{
		SessionFactory factory = new SessionFactory();
		List<ConnectionBean> list = factory.getMapper(LocalMapper.class).list(alias);
		factory.close();
		if(list!=null && !list.isEmpty())
		{
			ConnectionBean bean = list.get(0);
			txtAlias.setText(bean.getAlias());
			txtDbName.setText(bean.getDbname());
			txtDriver.setText(bean.getDriver());
			txtHost.setText(bean.getHost());
			txtPort.setText(String.valueOf(bean.getPort()));
			txtPwd.setText(bean.getPassword());
			txtUser.setText(bean.getUser());
			txtUrl.setText(bean.getUrl());
			int size = dbType.getModel().getSize();
			for (int i = 0; i < size; i++) {
				if(dbType.getModel().getElementAt(i).driver.equals(bean.getDriver()))
				{
					dbType.setSelectedIndex(i);
					break;
				}
			}
		}
	}
	/**
	 * 加载连接池列表
	 */
	void loadDBList() {
		SessionFactory factory = new SessionFactory();
		List<ConnectionBean> list = factory.getMapper(LocalMapper.class).list(null);
		factory.close();
		dtm.setRowCount(0);
		for (ConnectionBean bean : list) {
			String[] strs = new String[] { bean.getAlias(), bean.getDbname(), bean.getUser(), bean.getPassword(),
					bean.getHost(), String.valueOf(bean.getPort()), bean.getUrl() };
			dtm.addRow(strs);
		}
	}
	class TestConnection extends AbstractAction{
		DBSettingFrame frame;
		public TestConnection(DBSettingFrame frame)
		{
			putValue(NAME, "测试数据库连接");
			this.frame = frame;
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			try {
				Class.forName(frame.txtDriver.getText());
				DriverManager.getConnection(frame.txtUrl.getText(),frame.txtUser.getText(),frame.txtPwd.getText()).close();
				JOptionPane.showMessageDialog(frame, "数据库连接成功");
			} catch (ClassNotFoundException| SQLException e1) {
				JOptionPane.showMessageDialog(frame, "数据库连接失败，原因:"+e1.getMessage());
				e1.printStackTrace();
			}
		}
	}
	class DeleteAction extends AbstractAction {
		DBSettingFrame frame;

		public DeleteAction(DBSettingFrame frame) {
			this.frame = frame;
			putValue(NAME, "删除");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			int n = new SessionFactory().runTask(new SqlTask() {
				@Override
				public Object run(SessionFactory factory) {
					LocalMapper mapper = factory.getMapper(LocalMapper.class);
					return mapper.delete(txtAlias.getText());
				}
			}, Integer.class);
			frame.loadDBList();
			JOptionPane.showMessageDialog(frame, "已删除"+n+"条数据");
		}
	}
	class SaveAction extends AbstractAction {
		DBSettingFrame frame;

		public SaveAction(DBSettingFrame frame) {
			this.frame = frame;
			putValue(NAME, "保存");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			final ConnectionBean bean = new ConnectionBean();
			bean.setAlias(txtAlias.getText());
			bean.setDbname(txtDbName.getText());
			bean.setDriver(txtDriver.getText());
			bean.setHost(txtHost.getText());
			bean.setPassword(txtPwd.getText());
			bean.setPort(Integer.parseInt(txtPort.getText()));
			bean.setUrl(txtUrl.getText());
			bean.setUser(txtUser.getText());
			new SessionFactory().runTask(new SqlTask() {
				@Override
				public Object run(SessionFactory factory) {
					LocalMapper mapper = factory.getMapper(LocalMapper.class);
					List<ConnectionBean> list = mapper.list(txtAlias.getText());
					if (list.isEmpty()) {
						return mapper.add(bean);
					} else {
						return mapper.update(bean);
					}
				}
			}, Integer.class);
			frame.loadDBList();
		}
	}

	static class DBType {
		public static final String MYSQL_URL = "jdbc:mysql://${bean.host}:${bean.port}/${bean.dbname}";
		public static final String MYSQLDRIVER = "com.mysql.jdbc.Driver";
		public static final String SQLSERVERDRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
		public static final String SQLSERVER_URL = "jdbc:sqlserver://${bean.host}:${bean.port};databaseName=${bean.dbname}";
		public static final String SQLITEDRIVER = "org.sqlite.JDBC";
		public static final String SQLITE_URL = "jdbc:sqlite:/${bean.dbname}";

		public static final DBType MYSQL = new DBType("MYSQL", MYSQLDRIVER, MYSQL_URL);
		public static final DBType MSSQL = new DBType("MSSQL", SQLSERVERDRIVER, SQLSERVER_URL);
		public static final DBType SQLITE = new DBType("SQLITE", SQLITEDRIVER, SQLITE_URL);
		/**
		 * 显示名
		 */
		private String name;
		/**
		 * 驱动
		 */
		private String driver;
		/**
		 * 链接字符串
		 */
		private String urlPattern;

		private DBType(String name, String driver, String urlPattern) {
			super();
			this.name = name;
			this.driver = driver;
			this.urlPattern = urlPattern;
		}
		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Object#toString()
		 */
		@Override
		public String toString() {
			return name;
		}
	}
}
